#!/sw/bin/perl 

use threads;
use IO::Socket;
use IO::File;

use YAML;
use Data::Dumper;
use XML::Simple;


$| = 1;

my $log_path = "/ZhE/home/ZhE/documents/programming/perl/irc_client/logs";

my @server_refs = YAML::LoadFile( 'config.yaml' );
#my $ref = XMLin( 'login_data.xml' );

#my $server_refs = $ref->{ server };


my %server_threads; 

for ( @server_refs ) {
  my $host = $_->{ host };
  #  last if $_ eq NULL;
  print Dumper( $_ );
  &connect( $_ );
  &msg_send_join( $_ );
  $server_threads{ $host } = threads->create(\&listen, $_);
}

sleep 60;

while(1) { 
  sleep 1;
  query( $server_refs[0] );
}


sub query {
  
  my $ref = shift             || die "No data passed\n";
  my $sock = $ref->{ socket } || die "No socket passed\n";
  my $nick = $ref->{ nick }   || die "You should never see this\n";
  
  print STDOUT "\nInput message: "; 
  my $message = <>;
  
  print $sock ":$nick $message";
}
  

sub listen {

  my $ref = shift             || die "No data passed\n";
  my $sock = $ref->{ socket } || die "No socket for this channel\n";
  my $host = $ref->{ host }   || die "You should never see this\n";
  my $flog = $ref->{ log }    || warn "No log file present\n";
  
  while ( <$sock> ) {
    s/^\s*(\S*(?:\s+\S+)*)\s*$/$1/g;
    if (  m/^:([^!]+!~[^@]+\@[^ ]+|[^ ]+) ([A-Z]+|\d+) (.+)$/ ) {
      event_handler( $ref, $1, $2, $3 );
      my $fh = $ref->{ log };
      print $fh "$1 $2 $3\n";
    }
    
    for my $line (split( /\n\r/, $_ )) {
      $line =~ s/^\s*(\S*(?:\s+\S+)*)\s*$/$1/g;
      if ( $line =~ m/^PING(.+)/ ) {
        print $sock "PONG $1\r\n";
        print STDOUT "PONG$1\n";
      }
    }
  }
}

sub server_handler {
}

sub event_handler {
  my ($ref, $who, $command, $message) = @_;
  
  my ($nick, $ident, $host_mask) = split( /!~|@/, $who, 3 );
  
  print "$who**$command**$message\n";
  
  #return server_handler( $ref, $who, $command, $message ) if not $ident && $host_mask;
  

}


sub connect {
  my $ref       = shift               || die "No data passed\n";
  my $host      = $ref->{ host  }     || die "No host name provided";
  my $port      = $ref->{ port  }     || 6667;
  my $nick      = $ref->{ nick  }     || "Default";
  my $ident     = $ref->{ ident }     || "Default";
  my $real_name = $ref->{ real_name } || "Default";




  #$foo{ fh } = new IO::File("../logs/file", "a" );

#  $ref->{ log } = new IO::File( "../logs/$host", "a");
  print "$host $port $nick $ident\n\n";
  
  $ref->{ socket } = new IO::Socket::INET (
                                           PeerAddr => $host,
                                           PeerPort => $port,
                                           Proto => 'tcp'
                                          ) or die "Could not create socket";
  
  my $socket = $ref->{ socket };
  
  print $socket "NICK $nick \r\n";
  print $socket ":$nick USER $ident $host bla :$real_name\r\n";
}


# Sever operations - command passing
sub msg_send_pass {
  #    Command: PASS
  # Parameters: <password>
}

sub msg_send_nick {
  #    Command: NICK
  # Parameters: <nickname> [ <hopcount> ]
}

sub msg_send_user {
  #    Command: USER
  # Parameters: <username> <hostname> <servername> <realname>
}

sub msg_send_server {
  #    Command: SERVER
  # Parameters: <servername> <hopcount> <info>
}

sub msg_send_oper {
  #    Command: OPER
  # Parameters: <user> <password>
}

sub msg_send_quit {
  #    Command: QUIT
  # Parameters: [<Quit message>]
}

sub msg_send_squit {
  #    Command: SQUIT
  # Parameters: <server> <comment>
}



# Channel Operations
sub msg_send_join {
  #    Command: JOIN
  # Parameters: <channel>{,<channel>} [<key>{,<key>}]
  my $ref      = shift                   || die "No data passed\n";
  my $sock     = $ref->{ socket }        || die "No socket for this server\n";
  my $nick     = $ref->{ nick }          || die "You should never see this\n";
  my $channels = $ref->{ channels }      || die "No channels for this server\n";

  for my $channel ( @$channels ) {
    print Dumper( $channel );
    print STDOUT ":$nick JOIN $channel\n";
    print $sock  ":$nick JOIN $channel\r\n";
  }
}

sub msg_send_part {
  #    Command: PART
  # Parameters: <channel>{,<channel>}
}

sub msg_send_mode {
  #    Command: MODE
  # Parameters: <channel> {[+|-]|o|p|s|i|t|n|b|v} [<limit>] [<user>] [<ban mask>]
  # Parameters: <nickname> {[+|-]|i|w|s|o}
  #    The various modes available for channels are as follows:
  #       o - give/take channel operator privileges;
  #       p - private channel flag;
  #       s - secret channel flag;
  #       i - invite-only channel flag;
  #       t - topic settable by channel operator only flag;
  #       n - no messages to channel from clients on the outside;
  #       m - moderated channel;
  #       l - set the user limit to channel;
  #       b - set a ban mask to keep users out;
  #       v - give/take the ability to speak on a moderated channel;
  #       k - set a channel key (password).
  #    The available modes are as follows:
  #       i - marks a users as invisible;
  #       s - marks a user for receipt of server notices;
  #       w - user receives wallops;
  #       o - operator flag
}

sub msg_send_topic {
  #    Command: TOPIC
  # Parameters: <channel> [<topic>]
}

sub msg_send_names {
  #    Command: NAMES
  # Parameters: [<channel>{,<channel>}]
}

sub msg_send_list {
  #    Command: LIST
  # Parameters: [<channel>{,<channel>} [<server>]]
}

sub msg_send_invite {
  #    Command: INVITE
  # Parameters: <nickname> <channel>
}

sub msg_send_kick {
  #    Command: KICK
  # Parameters: <channel> <user> [<comment>]
}


# Server Queries and Commands
#    Command: VERSION
# Parameters: [<server>]
#    Command: STATS
# Parameters: [<query> [<server>]]
#    The currently supported queries are:
#       c - returns a list of servers which the server may connect to or allow connections from;
#       h - returns a list of servers which are either forced to be treated as leaves or allowed to act as hubs;
#       i - returns a list of hosts which the server allows a client to connect from;
#       k - returns a list of banned username/hostname combinations for that server;
#       l - returns a list of the server's connections, showing how long each connection has been established and the traffic over that connection in bytes and messages for each direction;
#       m - returns a list of commands supported by the server and the usage count for each if the usage count is non zero;
#       o - returns a list of hosts from which normal clients may become operators;
#       y - show Y (Class) lines from server's configuration file;
#       u - returns a string showing how long the server has been up.
#    Command: LINKS
# Parameters: [[<remote server>] <server mask>]
#    Command: TIME
# Parameters: [<server>]
#    Command: CONNECT
# Parameters: <target server> [<port> [<remote server>]]
#    Command: TRACE
# Parameters: [<server>]
#    Command: ADMIN
# Parameters: [<server>]
#    Command: INFO
# Parameters: [<server>]

# Private Messags
#    Command: PRIVMSG
# Parameters: <receiver>{,<receiver>} <text to be sent>
#    Command: NOTICE
# Parameters: <nickname> <text>

# Who Query
#    Command: WHO
# Parameters: [<name> [<o>]]
#    Command: WHOIS
# Parameters: [<server>] <nickmask>[,<nickmask>[,...]]
#    Command: WHOWAS
# Parameters: <nickname> [<count> [<server>]]

# Kill Message
#    Command: KILL
# Parameters: <nickname> <comment>

# Ping Message
#    Command: PING
# Parameters: <server1> [<server2>]

# Pong Message
#    Command: PONG
# Parameters: <daemon> [<daemon2>]

# Error Message
#    Command: ERROR
# Parameters: <error message>

#Optional Commnads
#   Command:	AWAY
#Parameters:	[message]
#   Command:	REHASH
#Parameters:	None
#   Command:	RESTART
#Parameters:	None
#   Command:	SUMMON
#Parameters:	<user> [<server>]
#   Command:	USERS
#Parameters:	[<server>]
#   Command:	WALLOPS
#Parameters:	Text to be sent to all operators currently online
